#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<string>
#include<iostream>
using namespace std;

#define ROW 21
#define COLUMN 16
constexpr auto COUNT = ROW * COLUMN;
static int global_num = 0;
static int lexCount = 0;

struct KeyWords {
	string sign;
	string desp;
	int number;
};

FILE* in1, * in2, * in3, * out;
string code[105];
int table[ROW][COLUMN];
char corres[COLUMN] = "+-*/%(){};><= ";

KeyWords keywords[10] = {
	{"int","int",0},
	{"char","char",1},
	{"float","float",2},
	{"if","if",3},
	{"while","while",4},
	{"then","then",5},
	{"else","else",6}
};

KeyWords rules[50];
KeyWords ans[505];

int pow(int a, int b)
{
	int num = 1;
	while (b--)
	{
		num *= a;
	}
	return num;
}

int readTableFile(const char *infile)
{
	if ((in1 = fopen(infile, "r")) == NULL)
	{
		printf("cannot open infile!\n");
		return 0;
	}

	int cnt = 0;
	while (1)
	{
		char tmpIn = fgetc(in1);
		int val = 0;
		while (tmpIn != ' ' && tmpIn != '\n' && tmpIn!=EOF)
		{
			val = val * 10 + (int)tmpIn - '0';
			tmpIn = fgetc(in1);
		}
		int row = cnt / COLUMN;
		int column = cnt % COLUMN;
		table[row][column] = val;
		if (tmpIn == EOF) break;
		cnt++;
	}
}

int judge(char ch)
{
	if ((ch >= 'a' && ch <= 'z') || (ch >= 'A') && (ch <= 'Z')) return 0;
	else if (ch >= '0' && ch <= '9') return 1;
	else {
		for (int i = 0; i < COLUMN; i++) {
			if (ch == corres[i]) return i + 2;
		}
		return -1;
	}
}

int readRules(const char *infile)
{
	if ((in2 = fopen(infile, "r")) == NULL)
	{
		printf("cannot open infile!\n");
		return 0;
	}
	int cnt = 0;
	while (1)
	{
		char tmpIn1 = fgetc(in2);
		if (tmpIn1 == EOF) break;
		while (tmpIn1 != ' ') {
			rules[cnt].sign += tmpIn1;
			tmpIn1 = fgetc(in2);
		}
		tmpIn1 = fgetc(in2);
		while (tmpIn1 != ' ') {
			rules[cnt].desp += tmpIn1;
			tmpIn1 = fgetc(in2);
		}
		rules[cnt].number = (int)fgetc(in2) - '0';
		if (fgetc(in2) == EOF) break;
		cnt++;
	}

}

int readCode(const char *filename)
{
	if ((in3 = fopen(filename, "r")) == NULL)
	{
		printf("cannot open infile!\n");
		return 0;
	}

	int count = 0; //��������������

	//ѭ����ȡÿһ�У�ֱ���ļ�β
	while (1)
	{
		char tmpIn = fgetc(in3);
		if (tmpIn == '\n')
		{
			count++;
			continue;
		}
		if (tmpIn == EOF) break;
		code[count] += tmpIn;
	}
	return count + 1;
}


void show(int state, string str)
{
	rules[state-1].sign = str;
	if (state == 1)
	{
		rules[state - 1].number = global_num++;
		for (int i = 0; i < 10; i++)
		{
			if (str == keywords[i].sign)
			{
				ans[lexCount++] = keywords[i];
				return;
			}
		}
	}
	if (state == 2)
	{
		rules[state - 1].number = stoi(str);
	}
	//cout << "(" << rules[state-1].sign << "," << rules[state-1].desp << "," << rules[state-1].number << ")" << endl;
	ans[lexCount++] = rules[state - 1];
}

void test() {
	for (int i = 0; i < ROW; i++) {
		for (int j = 0; j < COLUMN; j++) {
			cout << table[i][j] << " ";
		}
		cout << endl;
	}
	cout << endl << endl;
}


int analyse(string str)
{
	int state = 0;
	string tmpStr = "";
	for (int i = 0; i < str.size(); i++) {
		char tmp = str[i];
		int tmpState = state;
		int curr_ch = judge(tmp);
		if (curr_ch == -1)
		{
			return -1;
		}
		state = table[state][curr_ch];
		//cout << state << " " << tmp << " " << curr_ch << endl;
		
		if (state == 0)
		{
			i--;
			show(tmpState, tmpStr);
			tmpStr = "";
		}
		
		if (curr_ch == 15) { i++; continue; }
		if (state != 0) tmpStr += tmp;
		if (i == str.size() - 1) show(state, tmpStr);
	}
	return 1;
}

int main()
{
	readTableFile("table.txt");
	readRules("rule.txt");

	int state = 0;
	int count = readCode("test.txt");
	for (int i = 0; i < count; i++)
	{
		int success = analyse(code[i]);
		if (success == -1)
		{
			cout << "Row " << i + 1 << " error!" << endl;
			break;
		}
	}
	for (int i = 0; i < lexCount; i++)
	{
		cout << "(" << ans[i].sign << "," << ans[i].desp << "," << ans[i].number << ")" << endl;
	}
}